package xyz.xtt.exchange.service.impl;

import static java.util.stream.Collectors.toMap;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.ArrayList;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.Set;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.Function;
import java.util.stream.Collectors;

import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.stereotype.Service;

import com.google.common.collect.Sets;
import com.google.common.primitives.Longs;

import cn.hutool.core.collection.CollectionUtil;
import xyz.xtt.asset.api.enums.BizTypeEnum;
import xyz.xtt.asset.api.enums.SecondEnum;
import xyz.xtt.asset.api.enums.SellPatternEnum;
import xyz.xtt.asset.api.enums.StatusAllEnum;
import xyz.xtt.asset.client.response.AssetAccountResponse;
import xyz.xtt.asset.client.response.AssetDetailInfo;
import xyz.xtt.asset.client.response.AssetInfoResponse;
import xyz.xtt.asset.client.response.SecondAssetListVo;
import xyz.xtt.asset.client.response.TblAssetNoDto;
import xyz.xtt.asset.client.response.TransactionResponse;
import xyz.xtt.common.objects.DozerUtil;
import xyz.xtt.equity.api.dto.PackageDto;
import xyz.xtt.equity.api.dto.TblUserBenefitByAssetIdDto;
import xyz.xtt.equity.api.dto.TblUserBenefitByPackageDto;
import xyz.xtt.equity.api.enums.BenefitEnum;
import xyz.xtt.equity.client.request.TblUserBenefitDto;
import xyz.xtt.equity.client.response.AssetEntitlementResponse;
import xyz.xtt.exchange.constants.DeliverResult;
import xyz.xtt.exchange.constants.UpChainEnum;
import xyz.xtt.exchange.service.IDetailService;
import xyz.xtt.exchange.service.IInnerService;
import xyz.xtt.exchange.service.ITblMerchantInfoService;
import xyz.xtt.exchange.vo.BenefitVO;
import xyz.xtt.exchange.vo.InterestVo;
import xyz.xtt.exchange.vo.NftInterestDetailsVo;
import xyz.xtt.pay.client.request.BusinessOrderRequest;
import xyz.xtt.pay.client.response.BusinessOrderDto;
import xyz.xtt.user.client.response.UserInfoResponse;

/**
 * @author huqibo
 * @date 2025/03/19
 */
@Service
@RefreshScope
public class DetailServiceImpl implements IDetailService {
	@Autowired
	private IInnerService iInnerService;
	@Value("${asset.mint.canShelf:true}")
	private boolean canShelf;

	@Value("${asset.mint.secondTypeShelfTimeMinutes:5}")
	private Integer secondTypeShelfTimeMinutes;

	@Value("${asset.mint.max.price:10000}")
	private BigDecimal maxPriceNERemintType;
	@Autowired
	private ITblMerchantInfoService iTblMerchantInfoService;

	private Long queryAuthDate(String authorId) {
		UserInfoResponse userInfo = iInnerService.userInfo(Longs.tryParse(authorId));
		if (Objects.nonNull(userInfo)) {
			return userInfo.getAuthBefore();
		}
		return 0L;
	}

	public String getUserField(Map<Long, UserInfoResponse> userMap, Long uid, Function<? super UserInfoResponse, String> mapper) {
		if (!userMap.containsKey(uid)) {
			return StringUtils.EMPTY;
		}
		UserInfoResponse tblUser = userMap.get(uid);
		return getField(tblUser, mapper);
	}

	private String getField(UserInfoResponse seller, Function<? super UserInfoResponse, String> mapper) {
		return Optional.ofNullable(seller).map(mapper).filter(StringUtils::isNotBlank).orElse(StringUtils.EMPTY);
	}

	private Map<Long, UserInfoResponse> queryUsers(Set<Long> uids) {
		List<UserInfoResponse> userInfo = iInnerService.userInfo(uids);
		Map<Long, UserInfoResponse> map = userInfo.stream().collect(toMap(UserInfoResponse::getAppUserId, Function.identity()));
		return map;
	}

	public void buildDeliverResult(List<InterestVo> list, Long assetId, Long uid) {
		if (list.isEmpty()) {
			return;
		}
		// 兑换权益列表
		List<Long> deliverIds = iInnerService.entitlementDeliver(assetId, uid);
//		Set<Long> deliverIds = assetEntitlementDeliver.stream().map(TblAssetEntitlementDeliver::getId).collect(toSet());
//		if (assetEntitlementDeliver.isEmpty()) {
//			return list;
//		}
//		HashSet<String> deliverIds = new HashSet<>();
//		for (TblAssetEntitlementDeliver vo : assetEntitlementDeliver) {
//			if (vo.getResult().equals(1)) {
//				deliverIds.add(vo.getEntitlementId().toString());
//			}
//		}
		list = list.stream().peek(x -> {
			if (deliverIds.contains(Longs.tryParse(x.getId()))) {
				x.setResult(String.valueOf(DeliverResult.SUCC.code()));
			}
		}).toList();
	}

	@Override
	public NftInterestDetailsVo getNftDetails(Long assetAccountId, String goodsId, String uid) {
		Long uidL = Long.parseLong(uid);
		AssetDetailInfo assetBaseInfo = iInnerService.detailInfo(uid, goodsId, assetAccountId);
		if (null == assetBaseInfo) {
			return null;
		}
		// 组合数据
		Long assetId = assetBaseInfo.getAsset().getId();
		NftInterestDetailsVo build = NftInterestDetailsVo.build(assetBaseInfo);

		// 查询权益信息
		List<AssetEntitlementResponse> assetEntitlement = iInnerService.assetEntitlementWithAssetId(assetId);
		// 查询权益信息
		List<InterestVo> interestVo = DozerUtil.transforList(assetEntitlement, InterestVo.class);

		// 查询我是否拥有资产
		AssetAccountResponse myAccount = iInnerService.accountInfoCheckAmount(assetId, uidL);
//		TblAssetAccount myAccount = new LambdaQueryChainWrapper<>(tblAssetAccountMapper)
//				.eq(TblAssetAccount::getAssetId, assetId)
//				.eq(TblAssetAccount::getOwnerId, uidL)
//				.gt(TblAssetAccount::getAmount, 0)
//				.one();
		// 存在资产
		if (Objects.nonNull(myAccount) && Objects.equals(myAccount.getOwnerId(), uidL)) {
			buildDeliverResult(interestVo, assetId, uidL);
			// 可以加群
			build.setIsAddGroup(true);
			// 可以赠送
			build.setIsGiveAway(checkIsGiveAway(assetBaseInfo));
		}
		build.setInterestVoList(interestVo);
		// 处理用户名称 头像
		Long AuthorUid = Longs.tryParse(build.getAuthorId());
		Long ownerUId = Longs.tryParse(build.getOwnerId());
		Set<Long> uids = Sets.newHashSet(AuthorUid, ownerUId, uidL);
		Map<Long, UserInfoResponse> userMap = queryUsers(uids);
		build.setOwnerNickname(getUserField(userMap, ownerUId, UserInfoResponse::getNickname));
		build.setOwnerAvatar(getUserField(userMap, ownerUId, UserInfoResponse::getAvatarUri));
		build.setAuthorNickname(getUserField(userMap, AuthorUid, UserInfoResponse::getNickname));
		build.setAuthorAvatar(getUserField(userMap, AuthorUid, UserInfoResponse::getAvatarUri));
		build.setIssuer(getUserField(userMap, AuthorUid, UserInfoResponse::getNickname));
		build.setFoundryMan(getUserField(userMap, AuthorUid, UserInfoResponse::getNickname));
		build.setIssuerPlatform(getUserField(userMap, AuthorUid, UserInfoResponse::getNickname));
		UserInfoResponse tblUser = userMap.get(uidL);
		String gender = Optional.ofNullable(tblUser).map(UserInfoResponse::getGender).filter(Objects::nonNull).map(String::valueOf).orElse(StringUtils.EMPTY);
		build.setActiveParam(gender);

		// 查询交易
		TransactionResponse notPaiedTransaction = iInnerService.queryNotPaiedPersonalMintUpChaninOrder(assetId, uid);
		if (Objects.nonNull(notPaiedTransaction)) {
			build.setUpChainPaying(true);
		}

		// 设置群组ID
		if (Objects.nonNull(build.getIsAddGroup()) && build.getIsAddGroup()) {
			build.setImGroupId(assetBaseInfo.getGroupId());
		}
		// 设置资产可售数量
		build.setGoodsRemain(assetBaseInfo.getAssetAccount().getSellAmount() != null ? assetBaseInfo.getAssetAccount().getSellAmount().intValue() : 0);
		build.setCurrentDataTime(System.currentTimeMillis());
		build.setPublicityPeriod(assetBaseInfo.getAssetExt().checkPublicityPeriodEnd());
		build.setCurrAvatar(getUserField(userMap, uidL, UserInfoResponse::getAvatarUri));
		// 系统设置上架 并且 资产可售
		if (canShelf && (Objects.isNull(assetBaseInfo.getAsset().getSellable()) || StatusAllEnum.YES.code() == assetBaseInfo.getAsset().getSellable())) {
			// 判断上架状态 uid==authorId&&uid==ownerId&&sellPattern==0&&bizType==NFT&&Balance g 0
			if (Objects.equals(uidL, assetBaseInfo.getAssetAccount().getOwnerId())
					&& Objects.equals(assetBaseInfo.getAssetAccount().getSellPattern(), SellPatternEnum.NORMAL.code())
					&& BizTypeEnum.NFT.dbType().equalsIgnoreCase(assetBaseInfo.getAsset().getBizType()) && Objects.nonNull(myAccount)) {
				if (Objects.equals(uid, assetBaseInfo.getAsset().getAuthorId()) && assetBaseInfo.getAsset().isTopTrade(uid)) {
					build.setChainOver5Days(true);
				} else {
					build.setChainOver5Days(assetBaseInfo.getChainOverDays());
				}
			}

			// 重铸类型需要多判断5天的条件
			if (assetBaseInfo.getAsset().getSecondType().equals(SecondEnum.MINT_POWER.getCode())) {
				// 获取到拥有数量
				if (!assetBaseInfo.getChainOverDays()) {
					build.setChainOver5Days(false);
				}
			}
		}
		// 查询卡/编号
//		queryCardList(assetBaseInfo, uidL, build);
		if (assetBaseInfo.getAssetAccount().getOwnerId().equals(uidL)) {
			queryAssetNoList(assetBaseInfo, uidL, build);
		}
		// 查询最大购买价格
		BigDecimal bigDecimal = assetBaseInfo.getBuyMaxPriceWithHistory();
		build.setMaxPrice(bigDecimal.toString());
		build.setMaxPriceNERemintType(maxPriceNERemintType.divide(new BigDecimal(assetBaseInfo.getAsset().getAmount()), 2, RoundingMode.DOWN).toString());
		// 查询是否认证 把认证时间返回
		build.setPersonal(checkPersonal(build.getOwnerId()));
		build.setFirstBusiness(checkFirstBusiness(build.getOwnerId(), assetBaseInfo.getAsset()));
		// 添加权益
		TblUserBenefitByAssetIdDto benefitDetailInfo = iInnerService.getBenefitDetailInfo(uid, assetId);
		fillAssetBenefitList(benefitDetailInfo.getUserBenefitMap(), build);
		// 获取盲盒下图片列表
		build.setFileList(assetBaseInfo.getBoxSecondList().stream().map(SecondAssetListVo::getLogoUri).toList());
		return build;
	}

	/**
	 * 检查是否为一级交易
	 * 
	 * @param uid
	 * @param asset
	 * @return
	 */

	private Boolean checkFirstBusiness(String uid, AssetInfoResponse asset) {
		return Objects.equals(asset.getId(), asset.getRootAssetId()) && Objects.equals(asset.getAuthorId(), uid);
	}

	private void queryAssetNoList(AssetDetailInfo assetBaseInfo, Long uidL, NftInterestDetailsVo build) {
		// 获取用户资产编号信息
		List<TblAssetNoDto> assetNoList = assetBaseInfo.getAssetNoList();

		if (assetNoList.isEmpty()) {
			build.setAssetNoList(Collections.emptyList());
			return;
		}
		assetNoList.forEach(assetNo -> {
			assetNo.setAssetNo(String.format("%08d", Integer.valueOf(assetNo.getAssetNo())));
		});

		// 过滤出需要补充物流信息的卡片 ID 列表
		List<Long> idList = assetNoList.stream().map(TblAssetNoDto::getId).toList();
		// 获取物流订单信息
		Map<String, BusinessOrderDto> orderMap = getLogisticsOrderMap(uidL, idList);
		if (orderMap.isEmpty()) {
			build.setAssetNoList(assetNoList);
			return;
		}
		// 补充物流信息到卡片列表
		supplementLogisticsInfoByAssetNo(assetNoList, orderMap);
		build.setAssetNoList(assetNoList);
		build.setAssetNoId(assetNoList.get(0).getId());
	}

	private void supplementLogisticsInfoByAssetNo(List<TblAssetNoDto> assetNoList, Map<String, BusinessOrderDto> orderMap) {
		assetNoList.forEach(card -> {
			if (orderMap.containsKey(card.getId().toString())) {
				BusinessOrderDto businessOrderDto = orderMap.get(card.getId().toString());
				card.setLogisticsNumber(businessOrderDto.getTransportNo());
				card.setLogisticsCompanyName(businessOrderDto.getTransportCompany());
			}
		});
	}

	private Map<String, BusinessOrderDto> getLogisticsOrderMap(Long uidL, List<Long> idList) {
		BusinessOrderRequest businessOrderRequest = new BusinessOrderRequest();
		businessOrderRequest.setGoodsType(1);
		businessOrderRequest.setAppUserId(uidL);
		businessOrderRequest.setGoodsIds(idList);
		List<BusinessOrderDto> listApiResult = iInnerService.selectListByGoodsIds(businessOrderRequest);
		if (CollectionUtil.isNotEmpty(listApiResult)) {
			return listApiResult.stream().collect(Collectors.toMap(BusinessOrderDto::getGoodsId, Function.identity(), (v1, v2) -> v2));
		}
		return Collections.emptyMap();
	}

	private Boolean checkPersonal(String uid) {
		return !iTblMerchantInfoService.judgeMerchantPer(uid);
	}

	private void fillAssetBenefitList(LinkedHashMap<String, List<TblUserBenefitByPackageDto>> userBenefitMap, NftInterestDetailsVo build) {
		// 获取第一个非空条目
		Map.Entry<String, List<TblUserBenefitByPackageDto>> firstEntry = findNonEmptyEntry(userBenefitMap);
		if (firstEntry == null) {
			return; // 如果没有非空条目，直接返回
		}

		// 初始化资产收益列表
		List<BenefitVO> assetBenefitList = new ArrayList<>();
		build.setAssetBenefitList(assetBenefitList);

		// 遍历第一个非空条目的值
		firstEntry.getValue().forEach(tblUserBenefitDto -> {
			LinkedHashMap<PackageDto, List<TblUserBenefitDto>> userBenefitMap1 = tblUserBenefitDto.getUserBenefitMap();
			if (userBenefitMap1 != null && !userBenefitMap1.isEmpty()) {
				userBenefitMap1.forEach((packageDto, benefitList) -> {
					List<TblUserBenefitDto> list = benefitList.stream().filter(Objects::nonNull).filter(item -> item.getIsDel() == 0).toList();
					if (benefitList != null && !list.isEmpty()) {
						BenefitVO benefitVO = createBenefitVO(packageDto);
						processBenefits(benefitVO, list);
						assetBenefitList.add(benefitVO);
					}
				});
			}
		});
	}

	// 创建 BenefitVO 对象
	private BenefitVO createBenefitVO(PackageDto packageDto) {
		BenefitVO benefitVO = new BenefitVO();
		benefitVO.setBenefitPackage(packageDto.getPackageName());
		benefitVO.setSuffixType(0);
		benefitVO.setIfVIP(0);
		benefitVO.setBenefitPackageSuffix("");
		return benefitVO;
	}

	// 查找第一个非空条目，避免无限循环
	private Map.Entry<String, List<TblUserBenefitByPackageDto>> findNonEmptyEntry(LinkedHashMap<String, List<TblUserBenefitByPackageDto>> userBenefitMap) {
		for (Map.Entry<String, List<TblUserBenefitByPackageDto>> entry : userBenefitMap.entrySet()) {
			if (entry.getValue() != null && !entry.getValue().isEmpty()) {
				return entry;
			}
		}
		return null;
	}

	// 处理单个收益列表
	private void processBenefits(BenefitVO benefitVO, List<TblUserBenefitDto> benefitList) {
		AtomicInteger sortNo = new AtomicInteger(1);
		benefitList.forEach(item -> {
			// 防止空对象
			BenefitEnum benefitEnum = BenefitEnum.getByCode(item.getBenefitCode());
			if (benefitEnum != null) {
				String benefitDescription = sortNo.getAndIncrement() + "." + benefitEnum.getName() + "，剩余" + item.getBenefitRemain() + benefitEnum.getUnit();
				benefitVO.getBenefitPackageList().add(benefitDescription);

				if ("NFT_VIP_TAG".equalsIgnoreCase(benefitEnum.getCode())) {
					benefitVO.setSuffixType(1);
					benefitVO.setIfVIP(1);
					benefitVO.setBenefitPackageSuffix("有效期剩" + item.getBenefitRemain() + benefitEnum.getUnit());
				}
			}
		});
	}

	// 是否可赠送
	private Boolean checkIsGiveAway(AssetDetailInfo assetBaseInfo) {
		if (Objects.isNull(assetBaseInfo)) {
			return false;
		}

		// 如果没有资产 不能赠送
		if (BigDecimal.ZERO.equals(assetBaseInfo.getAssetAccount().getAmount())) {
			return false;
		}

		// 如果资产没有上链，则不进行赠送
		if (!Objects.equals(assetBaseInfo.getAssetExt().getUpChain(), UpChainEnum.YES.code())) {
			return false;
		}
		// 如果资产不允许赠送，则不进行赠送
		return !Objects.equals(assetBaseInfo.getAsset().getGiftable(), StatusAllEnum.NO.code());
	}
}
